#pragma once

#include "zqdb.h"
#include "zqstr.hpp"
#include "zqdb.pb.h"
#include "mdbdf.hpp"

namespace zqdb {

	template<class TStream>
	void SerializeTableTitleToCSV(TStream& os, HZQDB module, const char* table, const MDB_FIELD* attr, size_t attr_num)
	{
		for (size_t i = 0; i < attr_num; i++)
		{
			const char* name = ZQDBGetTableFiledName(module, table, i);
			if (i == 0) {
				if (name) {
					os << name;
				}
			}
			else {
				os << ",";
				if (name) {
					os << name;
				}
			}
		}
		os << "\n";
	}

	template<class TStream>
	void SerializeTableDataToCSV(TStream& os, const MDB_FIELD* attr, size_t attr_num, const char* data)
	{
		for (size_t i = 0; i < attr_num; i++)
		{
			if (i != 0) {
				os << ",";
			}
			char buf[1024] = { 0 };
			size_t buflen = 1024;
			char* sbuf = buf;
			char** val = &sbuf;
			size_t* sz = &buflen;
			mdb::FieldOp::GetValueAsStr(data, attr + i, 1, val, sz, nullptr);
			os << buf;
		}
		os << "\n";
	}

	template<class TStream>
	void SerializeDiffDataToCSV(TStream& os, size_t attr_num, const MDB_FIELD* diff, size_t diff_num, const char* data, bool code = false)
	{
		for (size_t i = 0, j = 0; i < attr_num; i++)
		{
			if (i != 0) {
				os << ",";
			}
			bool serialize = false;
			if (code) {
				if (MDB_FIELD_INDEX(ZQDB, CODE, CODE) == i) {
					serialize = true;
					os << ((CODEINFO*)data)->Code;
				}
				else if (MDB_FIELD_INDEX(ZQDB, CODE, EXCHANGE) == i) {
					serialize = true;
					os << ((CODEINFO*)data)->Exchange;
				}
			}
			if (!serialize) {
				for (; j < diff_num; )
				{
					if (diff[j].index > i) {
						break;
					}
					else if (diff[j].index == i) {
						char buf[1024] = { 0 };
						size_t buflen = 1024;
						char* sbuf = buf;
						char** val = &sbuf;
						size_t* sz = &buflen;
						mdb::FieldOp::GetValueAsStr(data, diff + j, 1, val, sz, nullptr);
						os << buf;
						j++;
						break;
					}
					else {
						j++;
					}
				}
			}
		}
		os << "\n";
	}

	template<class TStream>
	bool BuildDiffDataFromCSV(TStream& ss, const MDB_FIELD* field, MDB_FIELD* diff, size_t& diff_num, char* data, bool code = false)
	{
		std::string line;
		if (std::getline(ss, line)) {
			std::vector<std::string> vec;
			boost::split(vec, line, boost::is_any_of(","));
			for (size_t i = 0; i < vec.size(); i++)
			{
				if (vec[i].empty()) {
					continue;
				}
				const char* buf = vec[i].c_str();
				const size_t buflen = vec[i].size();
				const char** val = &buf;
				const size_t* sz = &buflen;
				mdb::FieldOp::SetValueAsStr(data, field + i, 1, val, sz);
				bool add_diff = true;
				if (code) {
					if (MDB_FIELD_INDEX(ZQDB, CODE, CODE) == i) {
						add_diff = false;
					}
					else if (MDB_FIELD_INDEX(ZQDB, CODE, EXCHANGE) == i) {
						add_diff = false;
					}
				}
				if (add_diff) {
					diff[diff_num++] = field[i];
				}
			}
			return true;
		}
		return false;
	}

}
